// 条件变量的封装 -- 条件变量组件
// 条件变量是同步机制 , 等待- 唤醒机制

// 防止头文件被重复包含 , 这里使用预处理方法
//  #ifndef .. #define .. #endif
#ifndef _COND_HPP_
#define _COND_HPP_

#include <iostream>
#include <pthread.h>
#include "Mutex.hpp"

namespace CondModel
{
    // 展开锁组件的命名空间
    using namespace MutexModel;

    class Cond
    {
    public:
        // 外部用 Cond 定义对象时 , 走构造函数直接创建条件变量
        Cond()
        {
            // 创建
            pthread_cond_init(&_cond, nullptr);
        }

        ////  1 . 等待

        // 在对应条件变量下等待 , 但是外部还要传一把锁
        void Wait(Mutex &mutex)
        {
            // 等待时要传一把锁 , 因为要释放
            // pthread_cond_wait(pthread_cond_t *restrict cond,
            // pthread_mutex_t *restrict mutex);
            // 传的是 Mutex 类 , 要的是里面的 pthread_mutex_t 锁类型
            // 但是  pthread_mutex_t 是 Mutex 类的私有成员 , 所以在 Mutex 中提供 Get函数
            int n = pthread_cond_wait(&_cond, &mutex.GetLock());
            if (n == 0)
            {
                std::cout << "wait cond success !" << std::endl;
            }
            else
            {
                std::cout << "wait cond fail !" << std::endl;
            }
        }

        //// 2 . 唤醒

        // 唤醒该条件变量下的单个线程
        void Signal()
        {
            int n = pthread_cond_signal(&_cond);
            if (n == 0)
            {
                std::cout << "signal thread success !" << std::endl;
            }
            else
            {
                std::cout << "signal thread fail !" << std::endl;
            }
        }

        // 唤醒该条件变量下的所有线程
        void BroadCast()
        {
            int n = pthread_cond_broadcast(&_cond);
            if (n == 0)
            {
                std::cout << "broadcast all thread success !" << std::endl;
            }
            else
            {
                std::cout << "broadcast all thread fail !" << std::endl;
            }
        }

        ~Cond()
        {
            // 销毁
            pthread_cond_destroy(&_cond);
        }

    private:
        pthread_cond_t _cond; // 条件变量类型变量
    };

}

#endif